#!/usr/local/bin/bash /usr/pkg/bin/bash

#
# $Id: rd_image.sh 171 2007-02-20 20:33:44Z seklecki $
# CF SVN Tag
# ====


#/*
# * Copyright (c) 2006-2007 Collaborative Fusion, Inc.  All rights reserved.
# * 
# * Developed by: Collaborative Fusion, Inc.
# *                                                     http://www.collaborativefusion.com
# * 
# * Permission is hereby granted, free of charge, to any person obtaining a copy
# * of this software and associated documentation files (the "Software"), to
# * deal with the Software without restriction, including without limitation the
# * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
# * sell copies of the Software, and to permit persons to whom the Software is
# * furnished to do so, subject to the following conditions:
# *   1. Redistributions of source code must retain the above copyright notice,
# *      this list of conditions and the following disclaimers.
# *   2. Redistributions in binary form must reproduce the above copyright
# *      notice, this list of conditions and the following disclaimers in the
# *      documentation and/or other materials provided with the distribution.
# *   3. All advertising materials mentioning features or use of this software
# *      must display the following acknowledgement: This product includes 
# *      software developed by Collaborative Fusion, Inc.
# *   4. Neither the name of Collaborative Fusion, Inc. or any of its employees
# *      may be used to endorse or promote products derived from this Software
# *      without specific prior written permission.
#
# * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 
# * COLLABORATIVE FUSION, INC. BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
# * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
# * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
# * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
# * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 
# * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
# */
#
#/*
# * This code was written under funding by Collaborative Fusion, Inc..
# */


# Copyright 2003 Gray Watson
#
# Permission to use, copy, modify, and distribute this software for
# any purpose and without fee is hereby granted, provided that the
# above copyright notice and this permission notice appear in all
# copies, and that the name of Gray Watson not be used in advertising
# or publicity pertaining to distribution of the document or software
# without specific, written prior permission.
#
# Gray Watson makes no representations about the suitability of the
# software described herein for any purpose.  It is provided "as is"
# without express or implied warranty.
#
# The author may be contacted via http://256.com/gray/
#
# This script builds a boot image to be written into a miniroot
# configured kernel file and booted from a Soekris system.  More
# information online:
#
# http://256.com/gray/docs/soekris_openbsd_diskless/
#


if [ ! -f "./cf.conf" ]; then
        echo "Cannot find cf.conf in ./ ...bailing out!";
        exit 1;
else
	echo "Source'ing in Conf"
        source ./cf.conf
fi

trap cleanup 1 2 3 14 15

DISKLABEL_TMP="$(${DISKLABEL_TMP_COMMAND})"

_intStepCount=0;

###############################################################################

echo "Building RD/MD In-Kernel FS Image for $PLATFORM"
echo "Copyright 2003 Gray Watson"
echo "NetBSD Adjustments 04/06 by Brian A. Seklecki <lavalamp@spiritual-machines.org>\
	<bseklecki@collaborativefusion.com>"


echo -n "Enter the filename to write the image into: [$IMAGE_FILE]"

read image_file
if [ "$image_file" = "" ]; then
    image_file=$IMAGE_FILE
fi

#################################################

# We only need to ask this in NetBSD/OpenBSD because FreeBSD dynamically loads MD/RD FS images

case ${PLATFORM} in 
	netbsd|openbsd)
		echo -n "Enter the kernel file to write the image into [$CFRD_KERNEL]: "
		read kernel_file
		if [ "$kernel_file" = "" ]; then
		    kernel_file=$CFRD_KERNEL
		fi
		
		if [ ! -f $kernel_file -o ! -r $kernel_file ] ; then
		echo "ERROR Kernel image file not found or not writable.
		echo "Please check size / permissions / crypto signature of file: ${kernel_file}
		exit 1
		fi
		;;
esac	

#################################################

case ${PLATFORM} in 
	netbsd|openbsd)

	echo "----------"
	
	echo "Step ${_intStepCount}: Checking for the ${KERN_RDMD_UTIL} utility in \$PATH."
	
	if [ ! -x $KERN_RDMD_UTIL ]; then
		cleanup
	fi
	;;
esac

#################################################

# NetBSD specific kernel const name change

cat << __EOF
----------
Please enter the configured number of MEMORY_DISK_ROOT_SIZE blocks from your
kernel configuration file.

__EOF
echo -n "MEMORY_DISK_ROOT_SIZE value: [${RD_SIZE}] "
read rd_size
if [ "$rd_size" = "" ]; then
        rd_size=${RD_SIZE}
fi

#################################################

cat << __EOF
----------
Enter the vnode device to use.  If you do not know what this is then
just press enter to take the default of "$VNODE_DEV".

__EOF
echo -n "Vnode device (FreeBSD will autopopulate later) [$VNODE_DEV]: "
read vnode_device

if [ "$vnode_device" = "" ]; then
    vnode_device=$VNODE_DEV
fi

#################################################

cat << __EOF
----------
Enter the directory path to the files that you want to load into the
ramdisk image.  The default is the directory $DEFAULT_ROOT in the current
directory.  If it doesn't exist then $DEFAULT2_ROOT is tried.  It is
assumed that this directory has the boot configuration files, and all
other information necessary for the system to work.

__EOF

default_root=$DEFAULT_ROOT
if [ ! -d $default_root ]; then
    default_root=$DEFAULT2_ROOT
fi

echo -n "Root filesystem directory [$default_root]: "
read root_dir

if [ "$root_dir" = "" ]; then
    root_dir=$default_root
fi

if [ ! -d $root_dir ]; then
    echo "I cannot see the directory $root_dir"
    exit 1
fi

############################################################################

# create the image file
echo "----------"

doit=yes
if [ -f $image_file  ]; then
    echo -n "Image file $image_file exists.  Re-zero or re-create it? [yes] "
    read doit
    if [ "$doit" = "" ]; then
        doit=yes
    fi
fi
if [ "$doit" = "yes" ]; then
    echo "Step ${_intStepCount}: Creating image file..."
    rm -f $image_file
    dd if=/dev/zero of=$image_file bs=512 count=$rd_size; good2go $?
fi

#################################################

# now map it into the vnode device
echo "----------"
echo "Step ${_intStepCount}: Mapping $image_file to vnode device $vnode_device."

case ${PLATFORM} in 
	netbsd|openbsd)
		vnconfig $vnode_device $image_file ; good2go $?
		;;
	freebsd)
		vnode_device=$(mdconfig -f $image_file)
		good2go $?
		;;
esac

#################################################

# get the current disk label
echo "----------"
echo "Step ${_intStepCount}: Getting the current disklabel from $vnode_device."
disklabel $vnode_device > $DISKLABEL_TMP

# At first after 6 months I was wondering what the fuck the "-e -I" was doing
# there , then I re-read this from the man page:
#
# The -I option is similar to the -r option but provides defaults instead
# of failing with an error, if there is no existing disklabel on the disk.
# 
# Go NetBSD!

DISKLABEL_RDCODE=$?

if [ ${PLATFORM} == "netbsd" -a ${DISKLABEL_RDCODE} -ne 0 ]; then
	# new disklabel in netbsd-4-* has warn codes > 100
	# that we can safely ignore with vnd(4)
	if [ ${DISKLABEL_RDCODE} -ne 102 ]; then
		echo "Getting the new disklabel from vnode device $vnode_device failed."
		cleanup
	fi
fi

# FreeBSD 7.x is apparently doing stupid shit too

if [ ${PLATFORM} == "freebsd" -a ${DISKLABEL_RDCODE} -ne 0 ]; then
	echo "FreeBSD doesn't autopopulate a kernel disklabel"	
fi


#################################################

# appending to the disk label
echo "Step ${_intStepCount}: Appending the new partition to the label."
case $PLATFORM in
	openbsd)
		echo "a:   $rd_size        0    4.2BSD    1024  8192  16 # (Cyl. 0 - $cylinders*)" >> $DISKLABEL_TMP
		;;
	freebsd)
		disklabel -w -m i386 ${vnode_device} auto
		;;
esac

case ${PLATFORM} in 
	netbsd|openbsd)
		disklabel -R $vnode_device $DISKLABEL_TMP; good2go $?
		rm -f $DISKLABEL_TMP
		;;
	freebsd)
		;;
esac


#################################################

# creating new filesystem
echo "Step ${_intStepCount}: Creating filesystem on /dev/r${vnode_device}a"

case ${PLATFORM} in 
	netbsd|openbsd)
		newfs -S 512 /dev/r${vnode_device}a ; good2go $?
		;;
	freebsd)
		newfs -S 512 /dev/${vnode_device}a; good2go $?
		;;
esac

#################################################

# making the new filesystem directory
echo "Step ${_intStepCount}: Making mount directory $VNODE_MOUNT."
mkdir $VNODE_MOUNT; good2go $?

#################################################

# mounting the new filesystem
echo "Step ${_intStepCount}: Mounting vnode device /dev/r${vnode_device}a on directory $VNODE_MOUNT."
case ${PLATFORM} in 
	netbsd|openbsd)
		mount /dev/${vnode_device}a $VNODE_MOUNT; good2go $?
		;;
	freebsd)
		mount /dev/${vnode_device}a ${VNODE_MOUNT}; good2go $?
		;;
esac


#################################################

# copy the files over to the new system

cat << __EOF
----------
Copying files from $root_dir to $VNODE_MOUNT (no boot):
__EOF

cd $root_dir && ${PAX} -rw -pe . ${HOME_DIR}/${VNODE_MOUNT} ; good2go $?

cd ${HOME_DIR}

###############################################################################

# syncing filesystems
sync

###############################################################################

# unmounting the image
sync
echo "Step ${_intStepCount}: Unmounting $VNODE_MOUNT."
case ${PLATFORM} in 
	netbsd|openbsd)
		umount $VNODE_MOUNT; good2go $?
		;;
	freebsd)
		umount ${HOME_DIR}/${VNODE_MOUNT}; good2go $?
		;;
esac

echo "Step ${_intStepCount}: Removing $VNODE_MOUNT directory."
rmdir $VNODE_MOUNT; good2go $?

echo "Step ${_intStepCount}: Removing vnode device $vnode_device."

case ${PLATFORM} in 
	netbsd|openbsd)
		vnconfig -u $vnode_device; good2go $?
		;;
	freebsd)
		mdconfig -d -u `echo ${vnode_device} | awk -F "md" '{print $2}'` ; good2go $?
		;;
esac


#################################################

# writing image into kernel
echo "Step ${_intStepCount}: Writing image file $image_file into kernel $kernel_file (if applicable)."

case $PLATFORM in
	netbsd)
		$KERN_RDMD_UTIL $kernel_file $image_file ; good2go $?
		;;
	openbsd)
		$KERN_RDMD_UTIL $kernel_file < $image_file ; good2go $?
		;;
	freebsd)
		echo "Copying image file $image_file to $CF_ROOT instead of writing to kernel."
		cp $image_file ${CF_ROOT}/boot/
		;;
esac


#################################################

# sync to disk
sync

echo "Done.  Updated kernel: $CFRD_KERNEL"

#################################################

echo "----------"

cf_root=$CF_ROOT

if [ ! -d $cf_root ]; then
    cf_root=$root_dir
fi

if [ -d $cf_root ]; then
    echo -n "Copy kernel $CFRD_KERNEL into CF root directory $cf_root? [yes] "
    read doit
    if [ "$doit" = "" ]; then
        doit=yes
    fi
    if [ "$doit" = "yes" ]; then
	case ${PLATFORM} in
		openbsd|netbsd)
			cp $CFRD_KERNEL $cf_root
			;;
		freebsd)
			mkdir -p ${cf_root}/boot/kernel
			cp $CFRD_KERNEL ${cf_root}/boot/kernel/
			if [ -n "$FREEBSD_KERNEL_MODULES" ]; then
				echo "Copying FreeBSD kernel modules to CF root directory: $FREEBSD_KERNEL_MODULES"
				for m in $FREEBSD_KERNEL_MODULES 
				do
					cp ${DSTDIR}/boot/kernel/$m ${cf_root}/boot/kernel/
				done
			fi
			;;
	esac

        if [ $? -ne 0 ]; then
            echo "Copying $image_file into CF root directory $cf_root failed."
            exit 1
        fi
        # sync to disk
        sync
        echo "Done."
    fi
fi
